#pragma once

#include "Common.h"
#include "Collider.h"

namespace Physics
{
    struct RigidBody
    {
        rp3d::RigidBody *m_Impl;

        void SetMass(const float &mass);

        float GetMass();

        bool IsActive();

        void SetIsActive(const bool v);

        enum class Type
        {
            STATIC,
            KINEMATIC,
            DYNAMIC
        };

        void SetBodyType(const Type &type);

        Type GetBodyType();

        glm::vec3 GetLinearVelocity() const;

        void SetLinearVelocity(const glm::vec3 &linearVelocity);

        glm::vec3 GetAngularVelocity() const;

        void SetAngularVelocity(const glm::vec3 &angularVelocity);

        const glm::vec3 &GetLocalInertiaTensor() const;

        void SetLocalInertiaTensor(const glm::vec3 &inertiaTensorLocal);

        const glm::vec3 &GetLocalCenterOfMass() const;

        void SetLocalCenterOfMass(const glm::vec3 &centerOfMass);

        bool IsGravityEnabled() const;

        void EnableGravity(bool isEnabled);

        bool IsSleeping() const;

        void SetIsSleeping(bool isSleeping);

        float GetLinearDamping() const;

        void SetLinearDamping(float linearDamping);

        float GetAngularDamping() const;

        void SetAngularDamping(float angularDamping);

        const glm::vec3 &GetLinearLockAxisFactor() const;

        void SetLinearLockAxisFactor(const glm::vec3 &linearLockAxisFactor) const;

        const glm::vec3 &GetAngularLockAxisFactor() const;

        void SetAngularLockAxisFactor(const glm::vec3 &angularLockAxisFactor) const;

        void SetTransform(const glm::vec3 &pos, const glm::quat &rot);

        void GetTransform(glm::vec3 &pos, glm::quat &rot);

        Physics::Collider AddBoxCollider(const glm::vec3 &halfExtends, const glm::vec3 &pos, const glm::quat &rot = glm::quat(1.0f, 0.0f, 0.0f, 0.0f));

        Physics::Collider AddSphereCollider(const float &radias, const glm::vec3 &pos, const glm::quat &rot = glm::quat(1.0f, 0.0f, 0.0f, 0.0f));

        Physics::Collider AddCapsuleCollider(const float &radius, const float &height, const glm::vec3 &pos, const glm::quat &rot = glm::quat(1.0f, 0.0f, 0.0f, 0.0f));

        enum class HeightDataType
        {
            HEIGHT_FLOAT_TYPE,
            HEIGHT_DOUBLE_TYPE,
            HEIGHT_INT_TYPE
        };

        Physics::Collider AddHeightFieldCollider(
            int nbGridColumns, int nbGridRows, float minHeight, float maxHeight,
            const void *heightFieldData, Physics::RigidBody::HeightDataType dataType,
            int upAxis, float integerHeightScale, const glm::vec3 &scaling,
            const glm::vec3 &pos,
            const glm::quat &rot = glm::quat(1.0f, 0.0f, 0.0f, 0.0f));

        Physics::Collider AddConvexMeshCollider(

            glm::vec3 *vertices, unsigned int numVertices,
            int *indices, unsigned int numIndices,
            unsigned int numFaces,
            unsigned int vertexStrideOfFace,
            const glm::vec3 &meshScaling,
            const glm::vec3 &pos,
            const glm::quat &rot = glm::quat(1.0f, 0.0f, 0.0f, 0.0f));

        Physics::Collider AddConcaveMeshColllider(
            glm::vec3 *vertices, unsigned int numVertices,
            int *indices, unsigned int numIndices,

            const glm::vec3 &meshScaling,
            const glm::vec3 &pos,
            const glm::quat &rot = glm::quat(1.0f, 0.0f, 0.0f, 0.0f));

    public:
        RigidBody(rp3d::RigidBody *impl);
    };
};
